#ifndef __VLOG_LOGFORMATTER_H__
#define __VLOG_LOGFORMATTER_H__

#include <memory>
#include <mutex>
#include <string>
#include <vector>

#include "logevent.h"

namespace vlog
{

class LogFormatter
{
    public:
    using ptr = std::shared_ptr<LogFormatter>;

    // 模板各个输出格式实现基类
    class FormatItemImpl
    {
        public:
        using ptr = std::shared_ptr<FormatItemImpl>;

        virtual ~FormatItemImpl()
        {
        }

        /// @brief 格式化日志事件
        /// @param os
        /// @param pEvent
        virtual void LogItemFormat(std::ostream& os, event::LogEvent::ptr pEvent) = 0;
    };

    public:
    /**
     * @brief [构造函数]
     * @param[in] pattern 格式模板 log4cpp
     *
     * @note 模板参数说明
     * - %%m 消息
     * - %%p 日志级别
     * - %%c 日志器名称
     * - %%d 日期时间，后面可跟一对括号指定时间格式，比如%d{%Y-%m-%d %H:%M:%S}，这里的格式字符与C语言strftime一致
     * - %%r 该日志器创建后的累计运行毫秒数
     * - %%f 文件名
     * - %%l 行号
     * - %%t 线程id
     * - %%F 协程id 目前不支持 没有接口获取协程id
     * - %%N 线程名称
     * - %%% 百分号
     * - %%T 制表符
     * - %%n 换行
     *
     * 默认格式：%d{%Y-%m-%d %H:%M:%S}%T%t%T%N%T%T[%p]%T[%c]%T%f:%l%T%m%n
     *
     * 默认格式描述：年-月-日 时:分:秒 [累计运行毫秒数] \\t 线程id \\t 线程名称\\t [日志级别] \\t [日志器名称] \\t
     * 文件名:行号 \\t 日志消息 换行符
     */
    explicit LogFormatter(const std::string& strPatter = "%d{%Y-%m-%d %H:%M:%S}%T%t%T%N%T%T[%p]%T[%c]%T%f:%l%T%m%n");

    bool IsError() const noexcept
    {
        return m_isError;
    }
    const std::string& GetPattern() const noexcept
    {
        return m_Pattern;
    }

    /**
     * @brief 获取日志事件格式化后的文本内容
     *
     * @return std::string 格式化后的内容
     *
     * @note [记录重要的补充信息]
     * @attention [标记需要特别注意的事项]
     * @bug [描述已知问题或潜在缺陷]
     */
    std::string Formatter(event::LogEvent::ptr pEvent);

    std::ostream& Formatter(std::ostream& os, event::LogEvent::ptr pEvent);

    private:
    // 解析patter 初始化 iteams
    void Init() noexcept;

    private:
    std::mutex m_mutex;

    // 日志格式模板
    std::string m_Pattern;
    // 解析后的模板项
    std::vector<FormatItemImpl::ptr> m_Items;
    bool m_isError = false;
};

} // namespace vlog

#endif